<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
   <link rel="stylesheet" type="text/css" href="stylesheet.css"/>
   <script type="text/javascript" src="js/pageToc.js"></script>
   <script type="text/javascript" src="js/sh/scripts/shCore.js"></script>
   <script type="text/javascript" src="js/sh/scripts/shBrushJScript.js"></script>
   <script type="text/javascript" src="js/sh/scripts/shBrushPhp.js"></script>
   <script type="text/javascript" src="js/sh/scripts/shBrushPlain.js"></script>
   <script type="text/javascript" src="js/sh/scripts/shBrushXml.js"></script>
   <link type="text/css" rel="stylesheet" href="js/sh/styles/shCore.css"/>
   <link type="text/css" rel="stylesheet" href="js/sh/styles/shThemeDefault.css"/>
   <script type="text/javascript">
   		SyntaxHighlighter.config.clipboardSwf = 'js/sh/scripts/clipboard.swf';
   		SyntaxHighlighter.all();
   </script>
   <title>PushButton Engine Lesson #5: Using and Embedding Images</title>
</head>
<body>

   <h1>PushButton Engine Lesson #5: Using and Embedding Images</h1>
   <p><center><em>"A novel is never anything but a philosophy put into images"</em> - Albert Camus</center></p>
   
   <p>The goal of this lesson is to guide the user in displaying images on the screen, and including them as embedded assets for distribution.</p>
   
   <p>These lessons are structured in a series of steps -- small milestones that will provide focused short-term goals for incrementally understanding PushButton Engine.</p>
   
   <p>These lessons are targeted at someone who is new to PBEngine, but not necessarily new to programming.</p>
   <div id="pageToc"></div>

   <div id="contentArea">   
   
   <h2>Tutorial Resources:</h2>
   <p>To follow along with the tutorial, you can download the starter project and use it as your base to implement the tutorial:
      <ul>
         <li><a href="downloads/Lesson5Base.zip">Lesson5Base.zip</a> (287KB)</li>
      </ul>
   The completed lesson files are available at the end of the tutorial.
   </p>
   <p>As covered in Lesson 1, extract the example .zip into a personal project folder, and ensure that it builds in your build environment.</p>
   
   <p>The built .swf of the base starter project should display a blue circle near the bottom of the screen, controllable via the keyboard.</p>
   
   <h2>Introduction to the Tutorial</h2>
   
   <p>Up until this point, all of the lessons have limited themselves to only display simple colors and shapes.  In this lesson, we will begin learning how to display and embed images.</p>
   
   <p><em>Technical Note:</em> There are a few different ways that one can embed assets into a compiled Flash file.  Because it is the most universal (accessible from Flash CS4 or Actionscript / Flex based tools), this tutorial will focus on embedding assets using Actionscript and the [Embed] metadata tag.</p>
   
   <p><h2>Showing Off</h2></p>
   
   <p>Nearly all functionality in PBE is given through components, and rendering sprites is no exception.  Remember that in previous lessons, we used SimpleShapeRenderComponent to display our hero as a blue circle.  To display our hero as a hovercraft sprite instead, we will replace that one render component with one we haven't looked at before -- a SpriteRenderComponent.</p>
   
   <p>The SpriteRenderComponent has very similar parameters to the shape renderer -- the primary difference is that it now needs a filename.  Because we also plan to add a background entity to the game in the next step, we will specify the layerIndex property of the render component, to ensure that the hero is drawn on top of the background.</p>
   
   <p>In the method createHero(), update the code that sets up the render component to be like the following:</p>
   
   <p><strong>File: /Lesson5Base/src/Lesson5Base.as</strong></p>
   <pre class="brush: js">
                  
       // Add our spatial component to the Hero entity ...
       createSpatial( hero,
           // with location of 0,150...
           new Point(0, 150),
           // and with size of 60,53...
           new Point(60, 53)
       );

       // Create a simple render component to display our object

       // Here we've removed the reference to our simple shape renderer, and added a sprite render component.
       var render:SpriteRenderer = new SpriteRenderer();

       // Tell the Render component to use one of the images embedded by our ResourceBundle
       render.fileName = "../assets/fanship.png";
       
       // Add the renderer to the scene.
       render.scene = PBE.scene;
       
       // Set our hero to render above the background.
       render.layerIndex = 10;
       
       // Point the render component to this entity's Spatial component for position information
       render.positionProperty = new PropertyReference("@Spatial.position");
       // Point the render component to this entity's Spatial component for size information
       render.sizeProperty = new PropertyReference("@Spatial.size");
      
       // Add our render component to the Hero entity with the name "Render"
       hero.addComponent( render, "Render" );
   </pre>

   <p><a href="images/Lesson5_2.png"><img src="images/Lesson5_2.png" align="right" width="204" height="159" alt="Goodbye cruel circle"></a></p>

   <p>At this point, you should be able to compile and run the game.  If everything was done correctly, then you should now see a small hovercraft in place of your old blue circle.</p>
   

   <p><em>Please note:</em> At this point, the hovercraft image is not embedded.  If you move or upload the SWF right now, it will not display any images.  This is fine for rapid development purposes, but to make the images work even after uploading or e-mailing the SWF, you will need the final step in this lesson -- embedding the images into the compiled SWF.</p>
   
   <p><h2>Adding the Background</h2></p>  

   <p>Next, we will add a new entity to display the background image.  This entity won't move, but will just sit in the center of the screen, and only serve to display the large background sprite.</p>
   
   <p>Everything in this section of code should be pretty familiar, as it's essentially a stripped down version of the Hero code.</p>

   <p><strong>File: /Lesson5Base/src/Lesson5Base.as</strong></p>
   <pre class="brush: js">
       private function createBackground():void
       {
          // Allocate an entity for our background sprite
          var bg:IEntity = PBE.allocateEntity();

          // Add our spatial component to the background entity ...
          createSpatial( bg, 
             // with location of 0,0...
             new Point(0, 0)
          );

          // Create a simple render component to display our object

          // Just like the hero, this also uses a SpriteRenderComponent
          var render:SpriteRenderer = new SpriteRenderer();

          // Tell the Render component to use one of the images embedded by our ResourceLinker
          render.fileName = "../assets/bg.jpg";

          // Set our background to render below the hero.
          render.layerIndex = 1;

          // Add the renderer to the scene.
          render.scene = PBE.scene;

          // Point the render component to this entity's Spatial component for position information
          render.positionProperty = new PropertyReference("@Spatial.position");

          // Add our render component to the BG entity with the name "Render"
          bg.addComponent( render, "Render" );

          // Register the entity with PBE under the name "BG"
          bg.initialize("BG");         
       }
   </pre>
   
   <p>And then at the top of the file, don't forget to add a call to createBackground().</p>

   <p><strong>File: /Lesson5Base/src/Lesson5Base.as</strong></p>
   <pre class="brush: js">
         // Create an avatar entity
         createHero();
         
         // Create a simple background entity
         createBackground();
   </pre>

   <p>Now you can compile and run your game!  Enjoy zooming your hovercraft over the rocky landscape.</p>

   <p><a href="images/Lesson5_1.png"><img src="images/Lesson5_1.png" width="204" height="159" alt="I can see clearly now"></a></p>

   <p><h2>Embedding the Assets</h2></p>
   <p>Previous to this step, the finished SWFs that you compiled need to have access to assets directory if they want to display images.  However, if you would like to distrubute your game (or just move it to a new section of your hard drive, away from the source), you will first need to embed the image resource into your SWF.</p> 

   <p>To help make embedding resources easier, PBE includes a ResourceBundle class.  This class interfaces with the ResourceManager to simplify the embedding process.</p>
   
   <p>The way to use the ResourceBundle is by creating and instantiating a class that inherits from it.</p>

   <p>To do this, create a new file in Lesson5Base/src/ called <em>MyResources.as</em> -- this will be our project's ResourceBundle.  Inside of the file, place the following code:</p>
   
   <p><strong>File: /Lesson5Base/src/MyResources.as</strong></p>
   <pre class="brush: js">
package
{
   import com.pblabs.engine.resource.*;
   
   public class MyResources extends ResourceBundle
   {
   }
}
   </pre>
   
   <p>Inside of the assets/ directory there are two image files -- <em>bg.jpg</em> and <em>fanship.png</em>.  To make the ResourceBundle aware of these files, you define a property of your descendant class that references the file with an [Embed] tag, like so:</p>
   
   <p><strong>File: /Lesson5Base/src/MyResources.as</strong></p>
   <pre class="brush: js">
   public class MyResources extends ResourceBundle
   {
      [Embed(source="../assets/bg.jpg")]
      public var resBg:Class;
      
      [Embed(source="../assets/fanship.png")]
      public var resShip:Class;
   }
   </pre>
   
   <p>In order for our custom ResourceBundle to be used, we need to instantiate it from our main class.  Inside of the Lesson5Base constructor, just after we make our call to Global.startup(), create a new instance of MyResources.</p>
   
   <p><strong>File: /Lesson5Base/src/Lesson5Base.as</strong></p>
   <pre class="brush: js">
      public function Lesson5Final()
      {
         // Start up PBE
         PBE.startup(this);
         
         // Load up our embedded resources
         new MyResources( );
   </pre>
   
   <p>And that should do it!  That will embed those graphics and make them accessible to PBE.  Once a ResourceBundle is instantiated, it automatically looks at the resources that you embedded inside of it, and properly registers them with the PBE ResourceManager.</p>

   <p>That should be the end of it!</p>
   
   <p><h2>Seeing Visions</h2></p>
   <p>After it's all compiled, you should have an .swf like the following (click to load):</p>
   <p><a href="downloads/Lesson5Final.swf"><img src="images/Lesson5_1.png" width="204" height="159" alt="Here or there, we can fly (and copy) our hovercraft anywhere!"></a></p>
      
   <p><h2>In Review</h2></p>

   <p><em>SpriteRenderComponent</em> can be used to render a sprite for an entity. Set the image of a <em>SpriteRenderComponent</em> through the fileName property.</p>
   
   <p>If you do not embed the assets into your compiled SWF, you will not be able to distribute your file to another location. The easiest (and most universal) way to embed resources in PBE is by using the <em>ResourceBundle</em>, although if you are using the CS4 Library, most components allow you to specify items from there directly (for instance <em>DisplayObjectRenderer</em> allows you to set its <em>displayObject</em> member with a direct reference to a <em>new ItemFromLibrary()</em>).</li>

   <p>To use ResourceBundle, use the following syntax:</p>

     <pre class="brush: js">
     public class MyResources extends ResourceBundle
     {
        [Embed(source="../assets/imageFilename.png")]
        public var someName:Class;
     }
     </pre>
 
    <p>Where <em>"../assets/imageFilename.png"</em> is the path to your resource, and <em>someName</em> is a unique property name inside of ResourceBundle.  This name is not as important as the filename, because all resources in PBE are referenced through the filename. It's not enough to just define your ResourceBundle class -- to actually make the assets accessible to PBE, the final step in making the assets embed is to instantiate your custom ResourceBundle class and register it with PBE:</p>
      
      <pre class="brush: js">
      PBE.addResources(new MyResources());
      </pre>
      
   <p><h2>Conclusion</h2></p>
   
   <p>Congratulations!  You have finished lesson #5, and loaded your first external assets into the game.</p>
   
   <p>This introduced more concepts than the previous lessons, but if you can master this, you will be much further along on your way to making games in PBE.</p>
    
   <p>You can download the completed project source files for this project.
      <ul>
         <li><a href="downloads/Lesson5Final.zip">Lesson5Final.zip</a> (288KB)</li>
      </ul>
   </p>
   </div>
</body>
</html>
